package com.harmony.pilot.knowledge.parser;

import com.harmony.pilot.knowledge.entity.CodeSnippet;
import com.harmony.pilot.knowledge.entity.FileMetadata;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 代码解析器
 * 将代码文件切分为有意义的片段，供LLM使用
 */
@Slf4j
@Component
public class CodeParser {
    
    // 函数定义的正则表达式
    private static final Pattern FUNCTION_PATTERN = Pattern.compile(
        "^\\s*(?:static\\s+)?(?:inline\\s+)?(?:virtual\\s+)?(?:const\\s+)?([\\w:]+(?:<[^>]+>)?\\s+[*&]*)([\\w]+)\\s*\\([^)]*\\)",
        Pattern.MULTILINE
    );
    
    // 类定义的正则表达式
    private static final Pattern CLASS_PATTERN = Pattern.compile(
        "^\\s*(?:class|struct|enum|union)\\s+([\\w]+)(?:\\s*:\\s*(?:public|private|protected)\\s+[\\w:,\\s]+)?\\s*\\{",
        Pattern.MULTILINE
    );
    
    // Include的正则表达式
    private static final Pattern INCLUDE_PATTERN = Pattern.compile(
        "^\\s*#include\\s+[\"<]([^>\"]+ )[>\"]",
        Pattern.MULTILINE
    );
    
    // GN构建目标的正则表达式
    private static final Pattern GN_TARGET_PATTERN = Pattern.compile(
        "(ohos_\\w+|executable|shared_library|static_library|source_set)\\s*\\(\\s*\"([^\"]+)\"\\s*\\)",
        Pattern.MULTILINE
    );
    
    /**
     * 解析文件并生成代码片段
     */
    public List<CodeSnippet> parseFile(FileMetadata metadata, String content) {
        List<CodeSnippet> snippets = new ArrayList<>();
        
        try {
            String fileType = metadata.getFileType();
            
            if (".gn".equals(fileType) || ".gni".equals(fileType)) {
                // 解析GN文件
                snippets.addAll(parseGnFile(metadata, content));
            } else {
                // 解析C/C++文件
                snippets.addAll(parseCppFile(metadata, content));
            }
            
        } catch (Exception e) {
            log.error("解析文件失败: {}", metadata.getFilePath(), e);
        }
        
        return snippets;
    }
    
    /**
     * 解析C/C++文件
     */
    private List<CodeSnippet> parseCppFile(FileMetadata metadata, String content) {
        List<CodeSnippet> snippets = new ArrayList<>();
        String[] lines = content.split("\n");
        
        // 1. 提取文件头 (包含版权、include等)
        CodeSnippet headerSnippet = extractFileHeader(metadata, lines);
        if (headerSnippet != null) {
            snippets.add(headerSnippet);
        }
        
        // 2. 提取所有include依赖
        List<String> includes = extractIncludes(content);
        
        // 3. 提取类定义
        snippets.addAll(extractClasses(metadata, content, includes));
        
        // 4. 提取函数定义
        snippets.addAll(extractFunctions(metadata, content, includes));
        
        // 5. 如果是测试文件，提取测试用例
        if (metadata.getIsTest()) {
            snippets.addAll(extractTestCases(metadata, content, includes));
        }
        
        // 6. 如果是Mock文件，提取Mock实现
        if (metadata.getIsMock()) {
            snippets.addAll(extractMockImplementations(metadata, content, includes));
        }
        
        // 7. 如果是Fuzzer文件，提取Fuzzer函数
        if (metadata.getIsFuzzer()) {
            snippets.addAll(extractFuzzerFunctions(metadata, content, includes));
        }
        
        return snippets;
    }
    
    /**
     * 提取文件头（版权、include、namespace等）
     */
    private CodeSnippet extractFileHeader(FileMetadata metadata, String[] lines) {
        StringBuilder header = new StringBuilder();
        int endLine = 0;
        
        // 提取开头的注释和include
        for (int i = 0; i < Math.min(lines.length, 100); i++) {
            String line = lines[i].trim();
            
            if (line.startsWith("//") || line.startsWith("/*") || line.startsWith("*") ||
                line.startsWith("#include") || line.startsWith("#ifndef") || 
                line.startsWith("#define") || line.startsWith("#endif") ||
                line.startsWith("namespace") || line.isEmpty()) {
                header.append(lines[i]).append("\n");
                endLine = i + 1;
            } else if (!line.isEmpty()) {
                break;
            }
        }
        
        if (header.length() > 50) {
            CodeSnippet snippet = new CodeSnippet();
            snippet.setFilePath(metadata.getFilePath());
            snippet.setRelativePath(metadata.getRelativePath());
            snippet.setModuleName(metadata.getModuleName());
            snippet.setSubModule(metadata.getSubModule());
            snippet.setSnippetType("FILE_HEADER");
            snippet.setContent(header.toString());
            snippet.setStartLine(1);
            snippet.setEndLine(endLine);
            snippet.setLineCount(endLine);
            snippet.setLanguage(metadata.getFileType().substring(1));
            snippet.setContentMd5(DigestUtils.md5Hex(header.toString()));
            snippet.setFileMd5(metadata.getFileMd5());
            snippet.setCopyrightInfo(metadata.getCopyright());
            snippet.setLicenseInfo(metadata.getLicense());
            snippet.setAuthorInfo(metadata.getAuthors());
            
            // 提取include
            List<String> includes = extractIncludes(header.toString());
            snippet.setIncludes(String.join(",", includes));
            
            return snippet;
        }
        
        return null;
    }
    
    /**
     * 提取include依赖
     */
    private List<String> extractIncludes(String content) {
        List<String> includes = new ArrayList<>();
        Matcher matcher = INCLUDE_PATTERN.matcher(content);
        while (matcher.find()) {
            includes.add(matcher.group(1));
        }
        return includes;
    }
    
    /**
     * 提取类定义
     */
    private List<CodeSnippet> extractClasses(FileMetadata metadata, String content, List<String> includes) {
        List<CodeSnippet> snippets = new ArrayList<>();
        Matcher matcher = CLASS_PATTERN.matcher(content);
        
        while (matcher.find()) {
            try {
                String className = matcher.group(1);
                int startPos = matcher.start();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                
                // 查找类的结束位置
                int endPos = findMatchingBrace(content, matcher.end());
                if (endPos > startPos) {
                    String classContent = content.substring(startPos, endPos);
                    int endLine = countLines(content.substring(0, endPos)) + 1;
                    
                    CodeSnippet snippet = new CodeSnippet();
                    snippet.setFilePath(metadata.getFilePath());
                    snippet.setRelativePath(metadata.getRelativePath());
                    snippet.setModuleName(metadata.getModuleName());
                    snippet.setSubModule(metadata.getSubModule());
                    snippet.setSnippetType("CLASS");
                    snippet.setContent(classContent);
                    snippet.setSummary("Class: " + className);
                    snippet.setStartLine(startLine);
                    snippet.setEndLine(endLine);
                    snippet.setLineCount(endLine - startLine + 1);
                    snippet.setLanguage(metadata.getFileType().substring(1));
                    snippet.setContentMd5(DigestUtils.md5Hex(classContent));
                    snippet.setFileMd5(metadata.getFileMd5());
                    snippet.setIncludes(String.join(",", includes));
                    snippet.setKeywords(className + ",class");
                    
                    // 元数据
                    snippet.setMetadata("{\"className\":\"" + className + "\",\"type\":\"class\"}");
                    
                    snippets.add(snippet);
                }
            } catch (Exception e) {
                log.warn("提取类定义失败", e);
            }
        }
        
        return snippets;
    }
    
    /**
     * 提取函数定义
     */
    private List<CodeSnippet> extractFunctions(FileMetadata metadata, String content, List<String> includes) {
        List<CodeSnippet> snippets = new ArrayList<>();
        Matcher matcher = FUNCTION_PATTERN.matcher(content);
        
        while (matcher.find()) {
            try {
                String returnType = matcher.group(1).trim();
                String functionName = matcher.group(2);
                int startPos = matcher.start();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                
                // 查找函数体
                int braceStart = content.indexOf('{', matcher.end());
                if (braceStart > 0) {
                    int endPos = findMatchingBrace(content, braceStart + 1);
                    if (endPos > startPos) {
                        String functionContent = content.substring(startPos, endPos);
                        int endLine = countLines(content.substring(0, endPos)) + 1;
                        
                        CodeSnippet snippet = new CodeSnippet();
                        snippet.setFilePath(metadata.getFilePath());
                        snippet.setRelativePath(metadata.getRelativePath());
                        snippet.setModuleName(metadata.getModuleName());
                        snippet.setSubModule(metadata.getSubModule());
                        snippet.setSnippetType("FUNCTION");
                        snippet.setContent(functionContent);
                        snippet.setSummary(returnType + " " + functionName + "(...)");
                        snippet.setStartLine(startLine);
                        snippet.setEndLine(endLine);
                        snippet.setLineCount(endLine - startLine + 1);
                        snippet.setLanguage(metadata.getFileType().substring(1));
                        snippet.setContentMd5(DigestUtils.md5Hex(functionContent));
                        snippet.setFileMd5(metadata.getFileMd5());
                        snippet.setIncludes(String.join(",", includes));
                        snippet.setKeywords(functionName + ",function," + returnType);
                        
                        // 元数据
                        snippet.setMetadata("{\"functionName\":\"" + functionName + 
                                          "\",\"returnType\":\"" + returnType + "\"}");
                        
                        snippets.add(snippet);
                    }
                }
            } catch (Exception e) {
                log.warn("提取函数定义失败", e);
            }
        }
        
        return snippets;
    }
    
    /**
     * 提取测试用例
     */
    private List<CodeSnippet> extractTestCases(FileMetadata metadata, String content, List<String> includes) {
        List<CodeSnippet> snippets = new ArrayList<>();
        
        // 匹配Google Test的TEST和TEST_F宏
        Pattern testPattern = Pattern.compile(
            "(TEST|TEST_F|TEST_P)\\s*\\(\\s*([^,]+)\\s*,\\s*([^)]+)\\s*\\)",
            Pattern.MULTILINE
        );
        
        Matcher matcher = testPattern.matcher(content);
        while (matcher.find()) {
            try {
                String testType = matcher.group(1);
                String testSuite = matcher.group(2).trim();
                String testName = matcher.group(3).trim();
                int startPos = matcher.start();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                
                int braceStart = content.indexOf('{', matcher.end());
                if (braceStart > 0) {
                    int endPos = findMatchingBrace(content, braceStart + 1);
                    if (endPos > startPos) {
                        String testContent = content.substring(startPos, endPos);
                        int endLine = countLines(content.substring(0, endPos)) + 1;
                        
                        CodeSnippet snippet = new CodeSnippet();
                        snippet.setFilePath(metadata.getFilePath());
                        snippet.setRelativePath(metadata.getRelativePath());
                        snippet.setModuleName(metadata.getModuleName());
                        snippet.setSubModule(metadata.getSubModule());
                        snippet.setSnippetType("TEST_CASE");
                        snippet.setContent(testContent);
                        snippet.setSummary(testType + "(" + testSuite + ", " + testName + ")");
                        snippet.setStartLine(startLine);
                        snippet.setEndLine(endLine);
                        snippet.setLineCount(endLine - startLine + 1);
                        snippet.setLanguage(metadata.getFileType().substring(1));
                        snippet.setContentMd5(DigestUtils.md5Hex(testContent));
                        snippet.setFileMd5(metadata.getFileMd5());
                        snippet.setIsTest(true);
                        snippet.setIncludes(String.join(",", includes));
                        snippet.setKeywords(testName + ",test," + testSuite);
                        
                        // 元数据
                        snippet.setMetadata("{\"testType\":\"" + testType + 
                                          "\",\"testSuite\":\"" + testSuite +
                                          "\",\"testName\":\"" + testName + "\"}");
                        
                        snippets.add(snippet);
                    }
                }
            } catch (Exception e) {
                log.warn("提取测试用例失败", e);
            }
        }
        
        return snippets;
    }
    
    /**
     * 提取Mock实现
     */
    private List<CodeSnippet> extractMockImplementations(FileMetadata metadata, String content, List<String> includes) {
        List<CodeSnippet> snippets = new ArrayList<>();
        
        // 匹配MOCK_METHOD宏
        Pattern mockPattern = Pattern.compile(
            "MOCK_METHOD\\d*\\s*\\([^)]+\\)",
            Pattern.MULTILINE
        );
        
        Matcher matcher = mockPattern.matcher(content);
        while (matcher.find()) {
            try {
                int startPos = matcher.start();
                int endPos = matcher.end();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                int endLine = countLines(content.substring(0, endPos)) + 1;
                
                String mockContent = content.substring(startPos, endPos);
                
                CodeSnippet snippet = new CodeSnippet();
                snippet.setFilePath(metadata.getFilePath());
                snippet.setRelativePath(metadata.getRelativePath());
                snippet.setModuleName(metadata.getModuleName());
                snippet.setSubModule(metadata.getSubModule());
                snippet.setSnippetType("MOCK");
                snippet.setContent(mockContent);
                snippet.setSummary("Mock method");
                snippet.setStartLine(startLine);
                snippet.setEndLine(endLine);
                snippet.setLineCount(endLine - startLine + 1);
                snippet.setLanguage(metadata.getFileType().substring(1));
                snippet.setContentMd5(DigestUtils.md5Hex(mockContent));
                snippet.setFileMd5(metadata.getFileMd5());
                snippet.setIsMock(true);
                snippet.setIncludes(String.join(",", includes));
                snippet.setKeywords("mock,MOCK_METHOD");
                
                snippets.add(snippet);
            } catch (Exception e) {
                log.warn("提取Mock实现失败", e);
            }
        }
        
        return snippets;
    }
    
    /**
     * 提取Fuzzer函数 (特别关注data和size参数)
     */
    private List<CodeSnippet> extractFuzzerFunctions(FileMetadata metadata, String content, List<String> includes) {
        List<CodeSnippet> snippets = new ArrayList<>();
        
        // 匹配Fuzzer入口函数: LLVMFuzzerTestOneInput
        Pattern fuzzerPattern = Pattern.compile(
            "int\\s+LLVMFuzzerTestOneInput\\s*\\(\\s*const\\s+uint8_t\\s*\\*\\s*(data|Data)\\s*,\\s*size_t\\s+(size|Size)\\s*\\)",
            Pattern.MULTILINE
        );
        
        Matcher matcher = fuzzerPattern.matcher(content);
        while (matcher.find()) {
            try {
                String dataParam = matcher.group(1);
                String sizeParam = matcher.group(2);
                int startPos = matcher.start();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                
                int braceStart = content.indexOf('{', matcher.end());
                if (braceStart > 0) {
                    int endPos = findMatchingBrace(content, braceStart + 1);
                    if (endPos > startPos) {
                        String fuzzerContent = content.substring(startPos, endPos);
                        int endLine = countLines(content.substring(0, endPos)) + 1;
                        
                        CodeSnippet snippet = new CodeSnippet();
                        snippet.setFilePath(metadata.getFilePath());
                        snippet.setRelativePath(metadata.getRelativePath());
                        snippet.setModuleName(metadata.getModuleName());
                        snippet.setSubModule(metadata.getSubModule());
                        snippet.setSnippetType("FUZZER");
                        snippet.setContent(fuzzerContent);
                        snippet.setSummary("LLVMFuzzerTestOneInput");
                        snippet.setStartLine(startLine);
                        snippet.setEndLine(endLine);
                        snippet.setLineCount(endLine - startLine + 1);
                        snippet.setLanguage(metadata.getFileType().substring(1));
                        snippet.setContentMd5(DigestUtils.md5Hex(fuzzerContent));
                        snippet.setFileMd5(metadata.getFileMd5());
                        snippet.setIsFuzzer(true);
                        snippet.setHasDataSizeParams(true);
                        snippet.setIncludes(String.join(",", includes));
                        snippet.setKeywords("fuzzer,LLVMFuzzerTestOneInput,data,size");
                        
                        // 元数据
                        snippet.setMetadata("{\"dataParam\":\"" + dataParam + 
                                          "\",\"sizeParam\":\"" + sizeParam + "\"}");
                        
                        snippets.add(snippet);
                    }
                }
            } catch (Exception e) {
                log.warn("提取Fuzzer函数失败", e);
            }
        }
        
        return snippets;
    }
    
    /**
     * 解析GN文件
     */
    private List<CodeSnippet> parseGnFile(FileMetadata metadata, String content) {
        List<CodeSnippet> snippets = new ArrayList<>();
        
        Matcher matcher = GN_TARGET_PATTERN.matcher(content);
        while (matcher.find()) {
            try {
                String targetType = matcher.group(1);
                String targetName = matcher.group(2);
                int startPos = matcher.start();
                int startLine = countLines(content.substring(0, startPos)) + 1;
                
                // 查找目标定义的结束位置
                int braceStart = content.indexOf('{', matcher.end());
                if (braceStart > 0) {
                    int endPos = findMatchingBrace(content, braceStart + 1);
                    if (endPos > startPos) {
                        String targetContent = content.substring(startPos, endPos);
                        int endLine = countLines(content.substring(0, endPos)) + 1;
                        
                        // 提取sources和deps
                        List<String> sources = extractGnArray(targetContent, "sources");
                        List<String> deps = extractGnArray(targetContent, "deps");
                        
                        CodeSnippet snippet = new CodeSnippet();
                        snippet.setFilePath(metadata.getFilePath());
                        snippet.setRelativePath(metadata.getRelativePath());
                        snippet.setModuleName(metadata.getModuleName());
                        snippet.setSubModule(metadata.getSubModule());
                        snippet.setSnippetType("GN_TARGET");
                        snippet.setContent(targetContent);
                        snippet.setSummary(targetType + "(\"" + targetName + "\")");
                        snippet.setStartLine(startLine);
                        snippet.setEndLine(endLine);
                        snippet.setLineCount(endLine - startLine + 1);
                        snippet.setLanguage("gn");
                        snippet.setContentMd5(DigestUtils.md5Hex(targetContent));
                        snippet.setFileMd5(metadata.getFileMd5());
                        snippet.setKeywords(targetName + ",gn," + targetType);
                        
                        // 元数据
                        snippet.setMetadata("{\"targetType\":\"" + targetType + 
                                          "\",\"targetName\":\"" + targetName +
                                          "\",\"sourceCount\":" + sources.size() +
                                          ",\"depCount\":" + deps.size() + "}");
                        
                        snippets.add(snippet);
                    }
                }
            } catch (Exception e) {
                log.warn("解析GN目标失败", e);
            }
        }
        
        // 如果没有找到特定目标，将整个文件作为一个片段
        if (snippets.isEmpty()) {
            CodeSnippet snippet = new CodeSnippet();
            snippet.setFilePath(metadata.getFilePath());
            snippet.setRelativePath(metadata.getRelativePath());
            snippet.setModuleName(metadata.getModuleName());
            snippet.setSubModule(metadata.getSubModule());
            snippet.setSnippetType("GN_BUILD");
            snippet.setContent(content);
            snippet.setSummary("GN Build File");
            snippet.setStartLine(1);
            snippet.setEndLine(metadata.getLineCount());
            snippet.setLineCount(metadata.getLineCount());
            snippet.setLanguage("gn");
            snippet.setContentMd5(DigestUtils.md5Hex(content));
            snippet.setFileMd5(metadata.getFileMd5());
            snippet.setKeywords("gn,build");
            
            snippets.add(snippet);
        }
        
        return snippets;
    }
    
    /**
     * 提取GN数组内容
     */
    private List<String> extractGnArray(String content, String arrayName) {
        List<String> items = new ArrayList<>();
        Pattern pattern = Pattern.compile(arrayName + "\\s*=\\s*\\[([^\\]]*)\\]", Pattern.DOTALL);
        Matcher matcher = pattern.matcher(content);
        
        if (matcher.find()) {
            String arrayContent = matcher.group(1);
            String[] lines = arrayContent.split("\n");
            for (String line : lines) {
                line = line.trim();
                if (line.startsWith("\"") && line.contains("\"")) {
                    String item = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                    items.add(item);
                }
            }
        }
        
        return items;
    }
    
    /**
     * 查找匹配的右括号
     */
    private int findMatchingBrace(String content, int startPos) {
        int braceCount = 1;
        for (int i = startPos; i < content.length(); i++) {
            char c = content.charAt(i);
            if (c == '{') {
                braceCount++;
            } else if (c == '}') {
                braceCount--;
                if (braceCount == 0) {
                    return i + 1;
                }
            }
        }
        return -1;
    }
    
    /**
     * 计算字符串中的行数
     */
    private int countLines(String text) {
        if (text.isEmpty()) return 0;
        return text.split("\n").length - 1;
    }
}

